home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / undel / part06 < prev    next >
Encoding:
Internet Message Format  |  1989-05-06  |  14.6 KB

  1. Path: uunet!bbn.com!rsalz
  2. From: rsalz@uunet.uu.net (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v18i078:  MIT Athena delete/undelete programs, Part06/06
  5. Message-ID: <1638@fig.bbn.com>
  6. Date: 29 Mar 89 04:33:55 GMT
  7. Lines: 649
  8. Approved: rsalz@uunet.UU.NET
  9.  
  10. Submitted-by: Jonathan I. Kamens <jik@PIT-MANAGER.MIT.EDU>
  11. Posting-number: Volume 18, Issue 78
  12. Archive-name: undel/part06
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 6 (of 6)."
  21. # Contents:  directories.c
  22. # Wrapped by jik@pit-manager on Mon Mar 27 12:16:56 1989
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'directories.c' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'directories.c'\"
  26. else
  27. echo shar: Extracting \"'directories.c'\" \(12581 characters\)
  28. sed "s/^X//" >'directories.c' <<'END_OF_FILE'
  29. X/*
  30. X * $Source: /mit/jik/src/delete/RCS/directories.c,v $
  31. X * $Author: jik $
  32. X * 
  33. X * This program is part of a package including delete, undelete,
  34. X * lsdel, expunge and purge.  The software suite is meant as a
  35. X * replacement for rm which allows for file recovery.
  36. X * 
  37. X * Copyright (c) 1989 by the Massachusetts Institute of Technology.
  38. X * For copying and distribution information, see the file "mit-copyright.h."
  39. X */
  40. X
  41. X#if !defined(lint) && !defined(SABER)
  42. X     static char rcsid_directories_c[] = "$Header: directories.c,v 1.12 89/03/27 12:06:16 jik Exp $";
  43. X#endif
  44. X
  45. X#include <sys/types.h>
  46. X#include <sys/stat.h>
  47. X#include <sys/param.h>
  48. X#include <sys/dir.h>
  49. X#include <strings.h>
  50. X#include "directories.h"
  51. X#include "util.h"
  52. X#include "mit-copyright.h"
  53. X
  54. Xextern char *malloc(), *realloc();
  55. Xextern char *whoami;
  56. X
  57. Xstatic filerec root_tree;
  58. Xstatic filerec cwd_tree;
  59. Xstatic char *error_buf;
  60. X
  61. X /* these are not static because external routines need to be able to */
  62. X /* access them. */
  63. Xlong current_time;
  64. X
  65. X
  66. Xstatic filerec default_cwd = {
  67. X     "",
  68. X     (filerec *) NULL,
  69. X     (filerec *) NULL,
  70. X     (filerec *) NULL,
  71. X     (filerec *) NULL,
  72. X     (filerec *) NULL,
  73. X     False,
  74. X     False,
  75. X     {0}
  76. X};
  77. X
  78. Xstatic filerec default_root = {
  79. X     "/",
  80. X     (filerec *) NULL,
  81. X     (filerec *) NULL,
  82. X     (filerec *) NULL,
  83. X     (filerec *) NULL,
  84. X     (filerec *) NULL,
  85. X     False,
  86. X     False,
  87. X     {0}
  88. X};
  89. X
  90. Xstatic filerec default_directory = {
  91. X     "",
  92. X     (filerec *) NULL,
  93. X     (filerec *) NULL,
  94. X     (filerec *) NULL,
  95. X     (filerec *) NULL,
  96. X     (filerec *) NULL,
  97. X     False,
  98. X     False,
  99. X     {0}
  100. X};
  101. X
  102. Xstatic filerec default_file = {
  103. X     "",
  104. X     (filerec *) NULL,
  105. X     (filerec *) NULL,
  106. X     (filerec *) NULL,
  107. X     (filerec *) NULL,
  108. X     (filerec *) NULL,
  109. X     False,
  110. X     False,
  111. X     {0}
  112. X};
  113. X
  114. X
  115. Xfilerec *get_root_tree()
  116. X{
  117. X     return(&root_tree);
  118. X}
  119. X
  120. X
  121. X
  122. Xfilerec *get_cwd_tree()
  123. X{
  124. X     return(&cwd_tree);
  125. X}
  126. X
  127. X
  128. Xinitialize_tree()
  129. X{
  130. X     int status;
  131. X     
  132. X     root_tree = default_root;
  133. X     cwd_tree = default_cwd;
  134. X
  135. X     current_time = time(0);
  136. X     error_buf = (char *) malloc(MAXPATHLEN + strlen(whoami) + 5);
  137. X     if (! error_buf) {
  138. X      return(1);
  139. X     }
  140. X     status = get_specs("", &cwd_tree.specs, FOLLOW_LINKS);
  141. X     if (! status)
  142. X      status = get_specs("/", &root_tree.specs, FOLLOW_LINKS);
  143. X     return(status);
  144. X}
  145. X
  146. X
  147. Xfilerec *add_path_to_tree(path)
  148. Xchar *path;
  149. X{
  150. X     filerec *parent, *leaf;
  151. X     char next_name[MAXNAMLEN];
  152. X     char lpath[MAXPATHLEN], built_path[MAXPATHLEN], *ptr;
  153. X     struct stat specs;
  154. X
  155. X     if (get_specs(path, &specs, DONT_FOLLOW_LINKS))
  156. X      return((filerec *) NULL);
  157. X     ptr = strcpy(lpath, path); /* we don't want to damage the user's string */
  158. X     if (*ptr == '/') {
  159. X      parent = &root_tree;
  160. X      ptr++;
  161. X      strcpy(built_path, "/");
  162. X     }
  163. X     else if (! strncmp(ptr, "./", 2)) {
  164. X      parent = &cwd_tree;
  165. X      ptr += 2;
  166. X      *built_path = '\0';
  167. X     }
  168. X     else {
  169. X      parent = &cwd_tree;
  170. X      *built_path = '\0';
  171. X     }
  172. X     
  173. X     strcpy(next_name, firstpart(ptr, ptr));
  174. X     while (*ptr) {
  175. X      strcat(built_path, next_name);
  176. X      parent = add_directory_to_parent(parent, next_name, False);
  177. X      if (! parent)
  178. X           return ((filerec *) NULL);
  179. X      strcpy(next_name, firstpart(ptr, ptr));
  180. X      if (get_specs(built_path, &parent->specs, FOLLOW_LINKS))
  181. X           return((filerec *) NULL);
  182. X      strcat(built_path, "/");
  183. X     }
  184. X     if ((specs.st_mode & S_IFMT) == S_IFDIR)
  185. X      leaf = add_directory_to_parent(parent, next_name, True);
  186. X     else
  187. X      leaf = add_file_to_parent(parent, next_name, True);
  188. X          
  189. X     if (! leaf)
  190. X      return ((filerec *) NULL);
  191. X     leaf->specs = specs;
  192. X
  193. X     return(leaf);
  194. X}
  195. X
  196. X
  197. X
  198. X
  199. Xget_specs(path, specs, follow)
  200. Xchar *path;
  201. Xstruct stat *specs;
  202. Xint follow;
  203. X{
  204. X     int status;
  205. X     
  206. X     if (strlen(path)) if ((path[strlen(path) - 1] == '/') &&
  207. X               (strlen(path) != 1))
  208. X      path[strlen(path) - 1] = '\0';
  209. X     if (follow == FOLLOW_LINKS)
  210. X      status = stat(path, specs);
  211. X     else 
  212. X      status = lstat(path, specs);
  213. X
  214. X     if (status)
  215. X      return(1);
  216. X     else
  217. X      return(0);
  218. X}
  219. X
  220. X
  221. X
  222. Xfilerec *next_leaf(leaf)
  223. Xfilerec *leaf;
  224. X{
  225. X     filerec *new;
  226. X
  227. X     if ((leaf->specs.st_mode & S_IFMT) == S_IFDIR) {
  228. X      new = first_in_directory(leaf);
  229. X      if (new)
  230. X           return(new);
  231. X      new = next_directory(leaf);
  232. X      return(new);
  233. X     }
  234. X     else {
  235. X      new = next_in_directory(leaf);
  236. X      return(new);
  237. X     }
  238. X}
  239. X
  240. X
  241. Xfilerec *next_specified_leaf(leaf)
  242. Xfilerec *leaf;
  243. X{
  244. X     while (leaf = next_leaf(leaf))
  245. X     if (leaf->specified)
  246. X      return(leaf);
  247. X     return((filerec *) NULL);
  248. X}
  249. X
  250. X
  251. Xfilerec *next_directory(leaf)
  252. Xfilerec *leaf;
  253. X{
  254. X     filerec *ret;
  255. X     if ((leaf->specs.st_mode & S_IFMT) != S_IFDIR)
  256. X      leaf = leaf->parent;
  257. X     if (leaf)
  258. X      ret = leaf->next;
  259. X     else
  260. X      ret = (filerec *) NULL;
  261. X     if (ret) if (ret->freed)
  262. X      ret = next_directory(ret);
  263. X     return(ret);
  264. X}
  265. X
  266. X
  267. Xfilerec *next_specified_directory(leaf)
  268. Xfilerec *leaf;
  269. X{
  270. X     while (leaf = next_directory(leaf))
  271. X      if (leaf->specified)
  272. X           return(leaf);
  273. X     return ((filerec *) NULL);
  274. X}
  275. X
  276. X
  277. X
  278. Xfilerec *next_in_directory(leaf)
  279. Xfilerec *leaf;
  280. X{
  281. X     filerec *ret;
  282. X
  283. X     if (leaf->next)
  284. X      ret = leaf->next;
  285. X     else if (((leaf->specs.st_mode & S_IFMT) != S_IFDIR) && leaf->parent)
  286. X      ret = leaf->parent->dirs;
  287. X     else
  288. X      ret = (filerec *) NULL;
  289. X     if (ret) if (ret->freed)
  290. X      ret = next_in_directory(ret);
  291. X     return (ret);
  292. X}
  293. X
  294. X
  295. X
  296. X
  297. Xfilerec *next_specified_in_directory(leaf)
  298. Xfilerec *leaf;
  299. X{
  300. X     while (leaf = next_in_directory(leaf))
  301. X      if (leaf->specified)
  302. X           return(leaf);
  303. X     return ((filerec *) NULL);
  304. X}
  305. X
  306. X
  307. X
  308. Xfilerec *first_in_directory(leaf)
  309. Xfilerec *leaf;
  310. X{
  311. X     filerec *ret;
  312. X
  313. X     if ((leaf->specs.st_mode & S_IFMT) != S_IFDIR)
  314. X      ret = (filerec *) NULL;
  315. X     else if (leaf->files)
  316. X      ret = leaf->files;
  317. X     else if (leaf->dirs)
  318. X      ret =  leaf->dirs;
  319. X     else
  320. X      ret = (filerec *) NULL;
  321. X     if (ret) if (ret->freed)
  322. X      ret = next_in_directory(ret);
  323. X     return(ret);
  324. X}
  325. X
  326. X
  327. Xfilerec *first_specified_in_directory(leaf)
  328. Xfilerec *leaf;
  329. X{
  330. X     leaf = first_in_directory(leaf);
  331. X     if (! leaf)
  332. X      return((filerec *) NULL);
  333. X     
  334. X     if (leaf->specified)
  335. X      return(leaf);
  336. X     else
  337. X      leaf = next_specified_in_directory(leaf);
  338. X     return (leaf);
  339. X}
  340. X
  341. X
  342. Xprint_paths_from(leaf)
  343. Xfilerec *leaf;
  344. X{
  345. X     char buf[MAXPATHLEN];
  346. X
  347. X     printf("%s\n", get_leaf_path(leaf, buf));
  348. X     if (leaf->dirs)
  349. X      print_paths_from(leaf->dirs);
  350. X     if (leaf->files)
  351. X      print_paths_from(leaf->files);
  352. X     if (leaf->next)
  353. X      print_paths_from(leaf->next);
  354. X     return(0);
  355. X}
  356. X
  357. X
  358. Xprint_specified_paths_from(leaf)
  359. Xfilerec *leaf;
  360. X{
  361. X     char buf[MAXPATHLEN];
  362. X
  363. X     if (leaf->specified)
  364. X      printf("%s\n", get_leaf_path(leaf, buf));
  365. X     if (leaf->dirs)
  366. X      print_specified_paths_from(leaf->dirs);
  367. X     if (leaf->files)
  368. X      print_specified_paths_from(leaf->files);
  369. X     if (leaf->next)
  370. X      print_specified_paths_from(leaf->next);
  371. X     return(0);
  372. X}
  373. X     
  374. X
  375. Xfilerec *add_file_to_parent(parent, name, specified)
  376. Xfilerec *parent;
  377. Xchar *name;
  378. XBoolean specified;
  379. X{
  380. X     filerec *files, *last = (filerec *) NULL;
  381. X
  382. X     files = parent->files;
  383. X     while (files) {
  384. X      if (! strcmp(files->name, name))
  385. X           break;
  386. X      last = files;
  387. X      files = files->next;
  388. X     }
  389. X     if (files) {
  390. X      files->specified = (files->specified || specified);
  391. X      return(files);
  392. X     }
  393. X     if (last) {
  394. X      last->next = (filerec *) malloc(sizeof(filerec));
  395. X      if (! last->next)
  396. X           return((filerec *) NULL);
  397. X      *last->next = default_file;
  398. X      last->next->previous = last;
  399. X      last->next->parent = parent;
  400. X      last = last->next;
  401. X     }
  402. X     else {
  403. X      parent->files = (filerec *) malloc(sizeof(filerec));
  404. X      if (! parent->files)
  405. X           return((filerec *) NULL);
  406. X      *parent->files = default_file;
  407. X      parent->files->parent = parent;
  408. X      parent->files->previous = (filerec *) NULL;
  409. X      last = parent->files;
  410. X     }
  411. X     strcpy(last->name, name);
  412. X     last->specified = specified;
  413. X     return(last);
  414. X}
  415. X
  416. X
  417. X
  418. X
  419. X
  420. Xfilerec *add_directory_to_parent(parent, name, specified)
  421. Xfilerec *parent;
  422. Xchar *name;
  423. XBoolean specified;
  424. X{
  425. X     filerec *directories, *last = (filerec *) NULL;
  426. X
  427. X     directories = parent->dirs;
  428. X     while (directories) {
  429. X      if (! strcmp(directories->name, name))
  430. X           break;
  431. X      last = directories;
  432. X      directories = directories->next;
  433. X     }
  434. X     if (directories) {
  435. X      directories->specified = (directories->specified || specified);
  436. X      return(directories);
  437. X     }
  438. X     if (last) {
  439. X      last->next = (filerec *) malloc(sizeof(filerec));
  440. X      if (! last->next)
  441. X           return((filerec *) NULL);
  442. X      *last->next = default_directory;
  443. X      last->next->previous = last;
  444. X      last->next->parent = parent;
  445. X      last = last->next;
  446. X     }
  447. X     else {
  448. X      parent->dirs = (filerec *) malloc(sizeof(filerec));
  449. X      if (! parent->dirs)
  450. X           return((filerec *) NULL);
  451. X      *parent->dirs = default_directory;
  452. X      parent->dirs->parent = parent;
  453. X      parent->dirs->previous = (filerec *) NULL;
  454. X      last = parent->dirs;
  455. X     }
  456. X     strcpy(last->name, name);
  457. X     last->specified = specified;
  458. X     return(last);
  459. X}
  460. X
  461. X
  462. X
  463. X
  464. X
  465. Xfree_leaf(leaf)
  466. Xfilerec *leaf;
  467. X{
  468. X     leaf->freed = True;
  469. X     if (! (leaf->dirs || leaf->files)) {
  470. X      if (leaf->previous)
  471. X           leaf->previous->next = leaf->next;
  472. X      if (leaf->next)
  473. X           leaf->next->previous = leaf->previous;
  474. X      if (leaf->parent) {
  475. X           if ((leaf->specs.st_mode & S_IFMT) == S_IFDIR) {
  476. X            if (leaf->parent->dirs == leaf) {
  477. X             leaf->parent->dirs = leaf->next;
  478. X             if (leaf->parent->freed)
  479. X                  free_leaf(leaf->parent);
  480. X            }
  481. X           }
  482. X           else {
  483. X            if (leaf->parent->files == leaf) {
  484. X             leaf->parent->files = leaf->next;
  485. X             if (leaf->parent->freed)
  486. X                  free_leaf(leaf->parent);
  487. X            }
  488. X           }
  489. X           free(leaf);
  490. X      }
  491. X     }
  492. X     return(0);
  493. X}     
  494. X
  495. X
  496. X
  497. Xfilerec *find_child(directory, name)
  498. Xfilerec *directory;
  499. Xchar *name;
  500. X{
  501. X     filerec *ptr;
  502. X
  503. X     if ((directory->specs.st_mode & S_IFMT) != S_IFDIR)
  504. X      return ((filerec *) NULL);
  505. X     ptr = directory->dirs;
  506. X     while (ptr)
  507. X      if (strcmp(ptr->name, name))
  508. X           ptr = ptr->next;
  509. X      else
  510. X           break;
  511. X     if (ptr)
  512. X      return (ptr);
  513. X     ptr = directory->files;
  514. X     while (ptr)
  515. X      if (strcmp(ptr->name, name))
  516. X           ptr = ptr->next;
  517. X          else
  518. X           break;
  519. X     if (ptr)
  520. X      return (ptr);
  521. X     return ((filerec *) NULL);
  522. X}
  523. X
  524. X
  525. X
  526. X
  527. X
  528. Xchange_path(old_path, new_path)
  529. Xchar *old_path, *new_path;
  530. X{
  531. X     char next_old[MAXNAMLEN], next_new[MAXNAMLEN];
  532. X     char rest_old[MAXPATHLEN], rest_new[MAXPATHLEN];
  533. X
  534. X     filerec *current;
  535. X
  536. X     if (*old_path == '/') {
  537. X      current = &root_tree;
  538. X      old_path++;
  539. X      new_path++;
  540. X     }
  541. X     else if (! strncmp(old_path, "./", 2)) {
  542. X      current = &cwd_tree;
  543. X      old_path += 2;
  544. X      new_path += 2;
  545. X     }
  546. X     else
  547. X      current = &cwd_tree;
  548. X
  549. X     strcpy(next_old, firstpart(old_path, rest_old));
  550. X     strcpy(next_new, firstpart(new_path, rest_new));
  551. X     while (*next_old && *next_new) {
  552. X      current = find_child(current, next_old);
  553. X      if (current)
  554. X           strcpy(current->name, next_new);
  555. X      else
  556. X           return(1);
  557. X      strcpy(next_old, firstpart(rest_old, rest_old));
  558. X      strcpy(next_new, firstpart(rest_new, rest_new));
  559. X     }
  560. X     if (! (*next_old || *next_new))
  561. X      return(0);
  562. X     else
  563. X      return(1);
  564. X}
  565. X
  566. X
  567. Xchar *get_leaf_path(leaf, leaf_buf)
  568. Xfilerec *leaf;
  569. Xchar leaf_buf[]; /* RETURN */
  570. X{
  571. X     char *name_ptr;
  572. X
  573. X     name_ptr = malloc(1);
  574. X     if (! name_ptr) {
  575. X      *leaf_buf = '\0';
  576. X      return(leaf_buf);
  577. X     }
  578. X     *name_ptr = '\0';
  579. X     do {
  580. X      name_ptr = realloc(name_ptr, strlen(leaf->name) + 
  581. X                 strlen(name_ptr) + 2);
  582. X      if (! name_ptr) {
  583. X           *leaf_buf = '\0';
  584. X           return(leaf_buf);
  585. X      }
  586. X      strcpy(leaf_buf, name_ptr);
  587. X      *name_ptr = '\0';
  588. X      if (leaf->parent) if (leaf->parent->parent)
  589. X           strcat(name_ptr, "/");
  590. X      strcat(name_ptr, leaf->name);
  591. X      strcat(name_ptr, leaf_buf);
  592. X      leaf = leaf->parent;
  593. X     } while (leaf);
  594. X     strcpy(leaf_buf, name_ptr);
  595. X     return(leaf_buf);
  596. X}
  597. X
  598. X
  599. X
  600. X
  601. X
  602. Xchar **accumulate_names(leaf, strings, num)
  603. Xfilerec *leaf;
  604. Xchar **strings;
  605. Xint *num;
  606. X{
  607. X     char newname[MAXPATHLEN];
  608. X     
  609. X     if (leaf->specified) {
  610. X      *num += 1;
  611. X      strings = (char **) realloc(strings, sizeof(char *) * (*num));
  612. X      if (! strings) {
  613. X           perror(sprintf(error_buf, "%s: accumulate_names", whoami));
  614. X           exit(1);
  615. X      }
  616. X      convert_to_user_name(get_leaf_path(leaf, newname), newname);
  617. X      strings[*num - 1] = malloc(strlen(newname) + 1);
  618. X      if (! strings[*num - 1]) {
  619. X           perror(sprintf(error_buf, "%s: accumulate_names", whoami));
  620. X           exit(1);
  621. X      }
  622. X      strcpy(strings[*num - 1], newname);
  623. X     }
  624. X     if (leaf->files)
  625. X      strings = accumulate_names(leaf->files, strings, num);
  626. X     if (leaf->dirs)
  627. X      strings = accumulate_names(leaf->dirs, strings, num);
  628. X     if (leaf->next)
  629. X      strings = accumulate_names(leaf->next, strings, num);
  630. X
  631. X     return(strings);
  632. X}
  633. END_OF_FILE
  634. if test 12581 -ne `wc -c <'directories.c'`; then
  635.     echo shar: \"'directories.c'\" unpacked with wrong size!
  636. fi
  637. # end of 'directories.c'
  638. fi
  639. echo shar: End of archive 6 \(of 6\).
  640. cp /dev/null ark6isdone
  641. MISSING=""
  642. for I in 1 2 3 4 5 6 ; do
  643.     if test ! -f ark${I}isdone ; then
  644.     MISSING="${MISSING} ${I}"
  645.     fi
  646. done
  647. if test "${MISSING}" = "" ; then
  648.     echo You have unpacked all 6 archives.
  649.     rm -f ark[1-9]isdone
  650. else
  651.     echo You still need to unpack the following archives:
  652.     echo "        " ${MISSING}
  653. fi
  654. ##  End of shell archive.
  655. exit 0
  656.  
  657. -- 
  658. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  659.  
  660.  
  661.